package org.visionlibrary.image.filters.rescaling;

import java.awt.image.ColorModel;

import javax.media.jai.TiledImage;

import org.visionlibrary.image.acquisition.ImageFactory;
import org.visionlibrary.image.model.AbstractFilter;


public class ExtendedNonlinearLevel extends AbstractFilter {
	double a = 0;
	double b = 0;
	protected int oldl = 256;
	protected int newl = 128;
	protected int[] lut;
	
	public ExtendedNonlinearLevel(int oldl, int newl, double a, double b) {
		this.oldl = oldl;
		this.newl = newl;
		this.a = a;
		this.b = b;
	}

	@Override
	public TiledImage applyFilter(TiledImage src, TiledImage dest) {
		if (null == src)
			throw new NullPointerException("Source image is null.");

		if (null == dest)
			dest = (new ImageFactory()).createCompatibleImage(src);

		int maxX = src.getWidth();
		int maxY = src.getHeight();
		for (int ch = 0; ch < src.getNumBands(); ch++) {
			ColorModel cm = src.getColorModel();
			int componentSize = cm.getComponentSize(ch);
			int length = (int) Math.pow(2, componentSize);

			lut = new int[length];
			
			double np = oldl * a;
			double ns = oldl * (1-a);
			double mp = newl * b;
			double ms = newl * (1-b);
			double t = 0.0;
			
			for (int i = 0; i < lut.length; i++) {
				if(i < np)
					t = (i-np)/np;
				else 
					t = (i-np)/ns;
				if(t < 0) 
					lut[i] = (int)(Math.pow(t*t*t,1/3.0f) * mp + mp);
				else 
					lut[i] = (int)(Math.pow(t*t*t,1/3.0f) * ms + mp);
			}

			for (int x = 0; x < maxX; x++)
				for (int y = 0; y < maxY; y++) {
					int pixel = src.getSample(x, y, ch);
					dest.setSample(x, y, ch, lut[pixel]);
				}
		}

		return dest;
	}
}
